" ## Installation ##
" 1. Install neovim, xclip
" 2. Then this config:
" mkdir -p ~/.config/nvim && cp init.vim ~/.config/nvim/
" 3. Install vim-plug:
" For *nix:
" curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \
"    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
" For Windows: https://github.com/junegunn/vim-plug
" 4. Then run `nvim`, ignore any errors and then :PlugInstall
" 5. Ctrl+w twice to exit and then use as normal


" ######## Prerequisites ######## "

" ---- OS Detection ---- "

if !exists('g:os_platform')
	if has('win64') || has('win32') || has('win16')
		let g:os_platform = 'WINDOWS'
	else
		let g:os_platform = toupper(substitute(system('uname'), '\n', '', ''))
	endif
endif
" ref: https://stackoverflow.com/a/51551652

" ---- Plugins ---- "

" Specify a directory for plugins
" - For Neovim: ~/.local/share/nvim/plugged
" - For Vim: ~/.vim/plugged
" - Avoid using standard Vim directory names like 'plugin'
call plug#begin('~/.local/share/nvim/plugged')

" Run :PlugInstall after adding a plugin
Plug 'scrooloose/nerdtree', { 'on':  'NERDTreeToggle' }
Plug 'crusoexia/vim-monokai'
Plug 'scrooloose/nerdcommenter'

" End of custom plugins
call plug#end()


" ######## General Configs (without plugins) ######## "


" ---- Basic stuff for display ---- "

syntax on
filetype plugin indent on
"colorscheme monokai
set cursorline      " Highlight cursor line
" highlight long lines
" more helpful than "set textwidth=80"
highlight ColorColumn ctermbg=magenta
call matchadd('ColorColumn', '\%81v', 100)
" for invisible characters
set listchars=eol:$,tab:>-,trail:~,extends:>,precedes:<,space:␣
"highlight SpecialKey ctermfg=8 ctermbg=8
"highlight link VisibleTab Error
"match VisibleTab /\t$/

" -- show row and column in footer + improved statusbar -- "
set ruler
set statusline=%F%m%r%h%w\ [%l,%c]\ [%L,%p%%]

" -- use mouse cursor (when needed badly) -- "
set mouse=a

" -- better line number -- "
" on normal mode, sets current line as current line and others as
" relative
set number relativenumber
" on insert mode, this is not needed, so restores normal line numbers
augroup numbertoggle
	autocmd!
	autocmd BufEnter,FocusGained,InsertLeave * set relativenumber
	autocmd BufLeave,FocusLost,InsertEnter   * set norelativenumber
augroup END

" -- Tab width -- "
" for using tabs for indenting
set sw=4
set tabstop=4

" -- Cursor style change depending on mode -- "
let &t_ti.="\e[1 q"
let &t_SI.="\e[5 q"
let &t_EI.="\e[1 q"
let &t_te.="\e[0 q"

" -- highlight the status bar when in insert mode -- "
if version >= 700
	au InsertEnter * hi StatusLine ctermfg=235 ctermbg=2
	au InsertLeave * hi StatusLine ctermbg=230 ctermfg=12
endif

" -- highlight trailing spaces in annoying red -- "
highlight ExtraWhitespace ctermbg=1 guibg=red
match ExtraWhitespace /\s\+$/
autocmd BufWinEnter * match ExtraWhitespace /\s\+$/
autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\@<!$/
autocmd InsertLeave * match ExtraWhitespace /\s\+$/
autocmd BufWinLeave * call clearmatches()


" ---- General Keyboard Shortcuts ---- "

" -- so that : commands can be typed quick! -- "
nnoremap ; :

" -- move cursor up and down even on insert mode -- "
inoremap <C-S-j> <ESC>ji
inoremap <C-S-k> <ESC>ki

" -- set leader key to comma -- "
let mapleader = ","

" -- Rename current file, via Gary Bernhardt -- "
function! RenameFile()
	let old_name = expand('%')
	let new_name = input('New file name: ', expand('%'))
	if new_name != '' && new_name != old_name
		exec ':saveas ' . new_name
		exec ':silent !rm ' . old_name
		redraw!
	endif
endfunction
map <leader>r :call RenameFile()<cr>

" -- exit insert with one hand! alternative to ESC or CAPS LOCK mod and faster -- "
inoremap jk <ESC>


" -- window/tab related keys -- "

" tab related
map <C-t> :tabnew<CR>
map <C-h> :tabp<CR>
map <C-l> :tabn<CR>

" -- save related -- "
function! SaveFile()
	let old_name = expand('%')
	if old_name != ''
		exec ':w'
	else
		let filename_input = input('Enter filename to save as: ')
		exec ':saveas ' . filename_input
	endif
endfunction
nnoremap <C-s> :call SaveFile()<cr>
inoremap <C-s> <Esc>:call SaveFile()<cr>i
vnoremap <C-s> <Esc>:call SaveFile()<cr>v

" -- close buffer related -- "
function! CloseFile()
	let old_name = expand('%')
	let unsaved_changes = &mod
	if unsaved_changes == 1
		" there are unsaved changes, so we offer to save
		let savechanges_input = input('Do you want to save changes? (y/n) ')
		if savechanges_input == 'y'
			:call SaveFile()
		endif
	endif
	exec ':q!'
	redraw!
endfunction
nnoremap <C-w> :call CloseFile()<cr>
inoremap <C-w> <Esc>:call CloseFile()<cr>
vnoremap <C-w> <Esc>:call CloseFile()<cr>



" -- Duplicate line -- "
vnoremap <C-S-D> y'>p<CR>
nnoremap <C-S-D> yypk<CR>

" -- Cut line -- "
vnoremap <C-k> d
nnoremap <C-k> dd

" -- move lines up and down -- "
nnoremap <C-M-j> :m .+1<CR>==
nnoremap <C-M-k> :m .-2<CR>==
inoremap <C-M-j> <Esc>:m .+1<CR>==gi
inoremap <C-M-k> <Esc>:m .-2<CR>==gi
vnoremap <C-M-j> :m '>+1<CR>gv=gv
vnoremap <C-M-k> :m '<-2<CR>gv=gv

" -- copy-paste systemwide (linux) -- "
" dependency: xclip
if g:os_platform =~ 'LINUX'
	vmap <C-c> y:call system("xclip -i -selection clipboard", getreg("\""))<CR>:call system("xclip -i", getreg("\""))<CR>
	vmap <C-x> d:call system("xclip -i -selection clipboard", getreg("\""))<CR>:call system("xclip -i", getreg("\""))<CR>
	nmap <C-v> :call setreg("\"",system("xclip -o -selection clipboard"))<CR>p
	imap <C-v> <Esc>:call setreg("\"",system("xclip -o -selection clipboard"))<CR>pi
	" to replace the selected text with text in clipboard
	vmap <C-v> x<Esc>h:call setreg("\"",system("xclip -o -selection clipboard"))<CR>p
endif
" ref: https://stackoverflow.com/a/20902777

" -- Select All -- "
nnoremap <C-a> ggVG
inoremap <C-a> <ESC>ggVG



" ######## Plugin Related ######## "

" ---- NerdTree related ---- "
map <C-o> :NERDTreeToggle<CR>

" ---- monokai related ---- "
colorscheme monokai

" ---- NerdCommenter related ---- "
nmap <C-_> ,c<space>
imap <C-_> <Esc>,c<space>i
vmap <buffer> <C-_> ,c<space>
" Add spaces after comment delimiters by default
let g:NERDSpaceDelims = 1
" Use compact syntax for prettified multi-line comments
"let g:NERDCompactSexyComs = 1
" Add your own custom formats or override the defaults
let g:NERDCustomDelimiters = { 'c': { 'left': '/**','right': '*/' } }
" Allow commenting and inverting empty lines (useful when commenting a region)
let g:NERDCommentEmptyLines = 1
" Enable trimming of trailing whitespace when uncommenting
let g:NERDTrimTrailingWhitespace = 1
